#include "CBasisFunction.h"
CBasisFunction::CBasisFunction(BASIS_TYPE type):
	m_dType(type),
	BASIS_ELE({
		{TWO_DIM_LINEAR,ELE_3},
		{TWO_DIM_BILINEAR,ELE_4},
		{TWO_DIM_QUADRATIC,ELE_6},
		{TWO_DIM_BIQUADRATIC,ELE_9}
		})
{
	
}

int CBasisFunction::getNumberBasis()
{
	return BASIS_ELE[m_dType];
}
double  CBasisFunction::FE_basis_local_func_2D(const CPoint &x, const vector<CPoint> &vertices, const BASIS_TYPE &basis_type, const int &basis_index, const int &basis_der_x, const int &basis_der_y) const
{
	if (TWO_DIM_LINEAR == basis_type || TWO_DIM_QUADRATIC == basis_type)
	{
		double x1 = vertices[0].getX();
		double y1 = vertices[0].getY();
		double x2 = vertices[1].getX();
		double y2 = vertices[1].getY();
		double x3 = vertices[2].getX();
		double y3 = vertices[2].getY();

		double J = fabs((x2 - x1)*(y3 - y1) - (x3 - x1)*(y2 - y1));
		CPoint xh;
		xh.setX(((y3 - y1)*(x.getX() - x1) - (x3 - x1)*(x.getY() - y1)) / J);
		xh.setY((-(y2 - y1)*(x.getX() - x1) + (x2 - x1)*(x.getY() - y1)) / J);
		xh.setZ(0);

		if (0 == basis_der_x && 0 == basis_der_y)//zero derivative of the basis function
		{
			return FE_reference_basis_func_2D(xh, basis_type, basis_index, basis_der_x, basis_der_y);
		}
		else if (1 == basis_der_x && 0 == basis_der_y)//first derivation of the basis function
		{
			return (y3 - y1) / J * FE_reference_basis_func_2D(xh, basis_type, basis_index, 1, 0)
				+ (y1 - y2) / J * FE_reference_basis_func_2D(xh, basis_type, basis_index, 0, 1);
		}
		else if (0 == basis_der_x && 1 == basis_der_y)
		{
			return  (x1 - x3) / J * FE_reference_basis_func_2D(xh, basis_type, basis_index, 1, 0)
				+ (x2 - x1) / J * FE_reference_basis_func_2D(xh, basis_type, basis_index, 0, 1);
		}
		else if (2 == basis_der_x && 0 == basis_der_y)
		{
			return pow(y3 - y1, 2) / pow(J, 2)*FE_reference_basis_func_2D(xh, basis_type, basis_index, 2, 0) +
				2 * (y3 - y1)*(y1 - y2) / pow(J, 2)*FE_reference_basis_func_2D(xh, basis_type, basis_index, 1, 1) +
				pow(y1 - y2, 2) / pow(J, 2)*FE_reference_basis_func_2D(xh, basis_type, basis_index, 0, 2);
		}
		else if (0 == basis_der_x && 2 == basis_der_y)
		{
			return pow(x1 - x3, 2) / pow(J, 2)*FE_reference_basis_func_2D(xh, basis_type, basis_index, 2, 0) +
				2 * (x1 - x3)*(x2 - x1) / pow(J, 2)*FE_reference_basis_func_2D(xh, basis_type, basis_index, 1, 1) +
				pow(x2 - x1, 2) / pow(J, 2)*FE_reference_basis_func_2D(xh, basis_type, basis_index, 0, 2);
		}
		else if (1 == basis_der_x && 1 == basis_der_y)
		{
			return (x1 - x3) * (y3 - y1) / pow(J, 2)*FE_reference_basis_func_2D(xh, basis_type, basis_index, 2, 0) +
				(x1 - x3) * (y1 - y2) / pow(J, 2)*FE_reference_basis_func_2D(xh, basis_type, basis_index, 1, 1) +
				(x2 - x1) * (y3 - y1) / pow(J, 2)*FE_reference_basis_func_2D(xh, basis_type, basis_index, 1, 1) +
				(x2 - x1) * (y1 - y2) / pow(J, 2)*FE_reference_basis_func_2D(xh, basis_type, basis_index, 0, 2);
		}
		else if (basis_der_x > 2 || basis_der_y > 2)
		{
			return 0;
		}

		else
		{
			cout << "\n error: wrong input for basis derivative\n";
			return 0;
		}

	}
	else if (TWO_DIM_BILINEAR == basis_type || TWO_DIM_BIQUADRATIC == basis_type)
	{

		//The reference basis functions defined in the slides of Prof. He require that 
		//the A1,A2,A3,A4 are the left-lower,right-lower,right-upper, and left-upper vertices respectively
		//However, the mesh generated by the gambit may not meet the requirement.
		//So we developed a general affine transformation
		double x1 = vertices[0].getX();
		double y1 = vertices[0].getY();
		double x2 = vertices[1].getX();
		double y2 = vertices[1].getY();
		double x3 = vertices[2].getX();
		double y3 = vertices[2].getY();
		double x4 = vertices[3].getX();
		double y4 = vertices[3].getY();

		double a = (-2 * y2 + 2 * y3) / (x1*y2 - x1 * y3 - x2 * y1 + x2 * y3 + x3 * y1 - x3 * y2);
		double b = (2 * x2 - 2 * x3) / (x1*y2 - x1 * y3 - x2 * y1 + x2 * y3 + x3 * y1 - x3 * y2);
		double c = (x1*y2 - x1 * y3 - x2 * y1 - x2 * y3 + x3 * y1 + x3 * y2) /
			(x1*y2 - x1 * y3 - x2 * y1 + x2 * y3 + x3 * y1 - x3 * y2);
		double d = (2 * y1 - 2 * y2) / (x1*y2 - x1 * y3 - x2 * y1 + x2 * y3 + x3 * y1 - x3 * y2);
		double e = (-2 * x1 + 2 * x2) / (x1*y2 - x1 * y3 - x2 * y1 + x2 * y3 + x3 * y1 - x3 * y2);
		double f = (x1*y2 + x1 * y3 - x2 * y1 - x2 * y3 - x3 * y1 + x3 * y2) /
			(x1*y2 - x1 * y3 - x2 * y1 + x2 * y3 + x3 * y1 - x3 * y2);
		double J = fabs((a*e - b * d) / pow(a*e - b * d, 2));

		CPoint xh;
		xh.setX(a * x.getX() + b * x.getY() + c);
		xh.setY(d * x.getX() + e * x.getY() + f);
		xh.setZ(0);


		if (0 == basis_der_x && 0 == basis_der_y)//zero derivative of the basis function
		{
			return FE_reference_basis_func_2D(xh, basis_type, basis_index, basis_der_x, basis_der_y);
		}
		else if (1 == basis_der_x && 0 == basis_der_y)//first derivation of the basis function
		{
			return a * FE_reference_basis_func_2D(xh, basis_type, basis_index, 1, 0) +
				d * FE_reference_basis_func_2D(xh, basis_type, basis_index, 0, 1);
		}
		else if (0 == basis_der_x && 1 == basis_der_y)
		{
			return  b * FE_reference_basis_func_2D(xh, basis_type, basis_index, 1, 0) +
				e * FE_reference_basis_func_2D(xh, basis_type, basis_index, 0, 1);

		}
		else if (1 == basis_der_x && 1 == basis_der_y)
		{
			return
				a * b*FE_reference_basis_func_2D(xh, basis_type, basis_index, 2, 0) +
				b * d*FE_reference_basis_func_2D(xh, basis_type, basis_index, 1, 1) +
				a * e*FE_reference_basis_func_2D(xh, basis_type, basis_index, 1, 1) +
				d * e*FE_reference_basis_func_2D(xh, basis_type, basis_index, 0, 2);

		}


	}

	return 0;
}

double CBasisFunction::FE_reference_basis_func_2D(const CPoint &xh, const BASIS_TYPE &basis_type, const int &basis_index, const int &basis_der_x, const int &basis_der_y) const
{
	double x = xh.getX();
	double y = xh.getY();
	if (basis_type == TWO_DIM_LINEAR)
	{
		if (basis_index == 0)
		{
			if (basis_der_x == 0 && basis_der_y == 0)
			{
				return -xh.getX() - xh.getY() + 1;
			}
			else if (basis_der_x == 0 && basis_der_y == 1)
			{
				return -1;
			}
			else if (basis_der_x == 1 && basis_der_y == 0)
			{
				return -1;
			}
			else if (basis_der_x == 1 && basis_der_y == 1)
			{
				return 0;
			}
			else
				return 0;

		}
		if (basis_index == 1)
		{
			if (basis_der_x == 0 && basis_der_y == 0)
			{
				return xh.getX();
			}
			else if (basis_der_x == 0 && basis_der_y == 1)
			{
				return 0;
			}
			else if (basis_der_x == 1 && basis_der_y == 0)
			{
				return 1;
			}
			else if (basis_der_x == 1 && basis_der_y == 1)
			{
				return 0;
			}
			else
				return 0;

		}
		if (basis_index == 2)
		{
			if (basis_der_x == 0 && basis_der_y == 0)
			{
				return xh.getY();
			}
			else if (basis_der_x == 0 && basis_der_y == 1)
			{
				return 1;
			}
			else if (basis_der_x == 1 && basis_der_y == 0)
			{
				return 0;
			}
			else if (basis_der_x == 1 && basis_der_y == 1)
			{
				return 0;
			}
			else
				return 0;

		}
	}
	else if (basis_type == TWO_DIM_QUADRATIC)
	{
		//It should be noted that the node order of gambit is different from the index of the local basis function given by Prof. He
		//The basis function index is defined by Prof. He as follow:
		//     3 
		//    / \
		//   6   5  
		//  /     \
		// 1___4___2
		//However, the order of the node in a element generated by gambit is defined as follow:
		//     5 
		//    / \
		//   6   4  
		//  /     \
		// 1___2___3
		if (basis_index == 0)
		{
			if (basis_der_x == 0 && basis_der_y == 0)
			{
				return 2 * pow(xh.getX(), 2) + 2 * pow(xh.getY(), 2) + 4 * xh.getX()*xh.getY() - 3 * xh.getY() - 3 * xh.getX() + 1;
			}
			else if (basis_der_x == 0 && basis_der_y == 1)
			{
				return 4 * xh.getX() + 4 * xh.getY() - 3;
			}
			else if (basis_der_x == 1 && basis_der_y == 0)
			{
				return 4 * xh.getX() + 4 * xh.getY() - 3;
			}
			else if (basis_der_x == 1 && basis_der_y == 1)
			{
				return 4;
			}
			else if (basis_der_x == 0 && basis_der_y == 2)
			{
				return 4;
			}
			else if (basis_der_x == 2 && basis_der_y == 0)
			{
				return 4;
			}
			else
				return 0;

		}
		if (basis_index == 2)
		{
			if (basis_der_x == 0 && basis_der_y == 0)
			{
				return 2 * pow(xh.getX(), 2) - xh.getX();
			}
			else if (basis_der_x == 0 && basis_der_y == 1)
			{
				return 0;
			}
			else if (basis_der_x == 1 && basis_der_y == 0)
			{
				return 4 * xh.getX() - 1;
			}
			else if (basis_der_x == 1 && basis_der_y == 1)
			{
				return 0;
			}
			else if (basis_der_x == 0 && basis_der_y == 2)
			{
				return 0;
			}
			else if (basis_der_x == 2 && basis_der_y == 0)
			{
				return 4;
			}
			else
				return 0;

		}
		if (basis_index == 4)
		{
			if (basis_der_x == 0 && basis_der_y == 0)
			{
				return 2 * pow(xh.getY(), 2) - xh.getY();
			}
			else if (basis_der_x == 0 && basis_der_y == 1)
			{
				return 4 * xh.getY() - 1;
			}
			else if (basis_der_x == 1 && basis_der_y == 0)
			{
				return 0;
			}
			else if (basis_der_x == 1 && basis_der_y == 1)
			{
				return 0;
			}
			else if (basis_der_x == 0 && basis_der_y == 2)
			{
				return 4;
			}
			else if (basis_der_x == 2 && basis_der_y == 0)
			{
				return 0;
			}
			else
				return 0;

		}
		if (basis_index == 1)
		{
			if (basis_der_x == 0 && basis_der_y == 0)
			{
				return -4 * pow(xh.getX(), 2) - 4 * xh.getX()*xh.getY() + 4 * xh.getX();
			}
			else if (basis_der_x == 0 && basis_der_y == 1)
			{
				return -4 * xh.getX();
			}
			else if (basis_der_x == 1 && basis_der_y == 0)
			{
				return -8 * xh.getX() - 4 * xh.getY() + 4;
			}
			else if (basis_der_x == 1 && basis_der_y == 1)
			{
				return -4;
			}
			else if (basis_der_x == 0 && basis_der_y == 2)
			{
				return 0;
			}
			else if (basis_der_x == 2 && basis_der_y == 0)
			{
				return -8;
			}
			else
				return 0;

		}
		if (basis_index == 3)
		{
			if (basis_der_x == 0 && basis_der_y == 0)
			{
				return 4 * xh.getX()*xh.getY();
			}
			else if (basis_der_x == 0 && basis_der_y == 1)
			{
				return 4 * xh.getX();
			}
			else if (basis_der_x == 1 && basis_der_y == 0)
			{
				return 4 * xh.getY();
			}
			else if (basis_der_x == 1 && basis_der_y == 1)
			{
				return 4;
			}
			else if (basis_der_x == 0 && basis_der_y == 2)
			{
				return 0;
			}
			else if (basis_der_x == 2 && basis_der_y == 0)
			{
				return 0;
			}
			else
				return 0;

		}

		if (basis_index == 5)
		{
			if (basis_der_x == 0 && basis_der_y == 0)
			{
				return -4 * pow(xh.getY(), 2) - 4 * xh.getX()*xh.getY() + 4 * xh.getY();
			}
			else if (basis_der_x == 0 && basis_der_y == 1)
			{
				return -4 * xh.getX() - 8 * xh.getY() + 4;
			}
			else if (basis_der_x == 1 && basis_der_y == 0)
			{
				return -4 * xh.getY();
			}
			else if (basis_der_x == 1 && basis_der_y == 1)
			{
				return -4;
			}
			else if (basis_der_x == 0 && basis_der_y == 2)
			{
				return -8;
			}
			else if (basis_der_x == 2 && basis_der_y == 0)
			{
				return 0;
			}
			else
				return 0;

		}
	}
	else if (basis_type == TWO_DIM_BILINEAR)
	{

		//define basis function on reference element([-1,-1],[1,-1],[1,1],[-1,1])

		if (basis_index == 0)
		{
			if (basis_der_x == 0 && basis_der_y == 0)
			{
				return (1 - xh.getX() - xh.getY() + xh.getX()*xh.getY()) / 4.0;
			}
			else if (basis_der_x == 1 && basis_der_y == 0)
			{
				return (-1 + xh.getY()) / 4.0;
			}
			else if (basis_der_x == 0 && basis_der_y == 1)
			{
				return (-1 + xh.getX()) / 4.0;
			}
			else if (basis_der_x == 1 && basis_der_y == 1)
			{
				return 1.0 / 4.0;
			}
			else
				return 0;
		}
		if (basis_index == 1)
		{
			if (basis_der_x == 0 && basis_der_y == 0)
			{
				return (1 + xh.getX() - xh.getY() - xh.getX()*xh.getY()) / 4.0;
			}
			else if (basis_der_x == 1 && basis_der_y == 0)
			{
				return (1 - xh.getY()) / 4.0;
			}
			else if (basis_der_x == 0 && basis_der_y == 1)
			{
				return (-1 - xh.getX()) / 4.0;
			}
			else if (basis_der_x == 1 && basis_der_y == 1)
			{
				return -1.0 / 4.0;
			}

			else
				return 0;
		}
		if (basis_index == 2)
		{
			if (basis_der_x == 0 && basis_der_y == 0)
			{
				return (1 + xh.getX() + xh.getY() + xh.getX()*xh.getY()) / 4.0;
			}
			else if (basis_der_x == 1 && basis_der_y == 0)
			{
				return (1 + xh.getY()) / 4.0;
			}
			else if (basis_der_x == 0 && basis_der_y == 1)
			{
				return (1 + xh.getX()) / 4.0;
			}
			else if (basis_der_x == 1 && basis_der_y == 1)
			{
				return 1.0 / 4.0;
			}
			else
				return 0;
		}
		if (basis_index == 3)
		{
			if (basis_der_x == 0 && basis_der_y == 0)
			{
				return (1 - xh.getX() + xh.getY() - xh.getX()*xh.getY()) / 4.0;
			}
			else if (basis_der_x == 1 && basis_der_y == 0)
			{
				return (-1 - xh.getY()) / 4.0;
			}
			else if (basis_der_x == 0 && basis_der_y == 1)
			{
				return (1 - xh.getX()) / 4.0;
			}
			else if (basis_der_x == 1 && basis_der_y == 1)
			{
				return -1.0 / 4.0;
			}
			else
				return 0;
		}
	}
	else if (basis_type == TWO_DIM_BIQUADRATIC)
	{
		//The reference basis functions and their derivatives are obtained by the symbolic calculation with python in the file "basis_fun_biquadratic_2D.py"
		if (basis_index == 0)
		{
			if (basis_der_x == 0 && basis_der_y == 0)
			{
				return pow(xh.getX(), 2) * pow(xh.getY(), 2) / 4 - pow(xh.getX(), 2) * xh.getY() / 4 - xh.getX() * pow(xh.getY(), 2) / 4 + xh.getX() * xh.getY() / 4;
			}
			else if (basis_der_x == 1 && basis_der_y == 0)
			{
				return xh.getX() *  pow(xh.getY(), 2) / 2 - xh.getX() * xh.getY() / 2 - pow(xh.getY(), 2) / 4 + xh.getY() / 4;
			}
			else if (basis_der_x == 0 && basis_der_y == 1)
			{
				return pow(xh.getX(), 2) * xh.getY() / 2 - pow(xh.getX(), 2) / 4 - xh.getX() * xh.getY() / 2 + xh.getX() / 4;
			}
			else if (basis_der_x == 1 && basis_der_y == 1)
			{
				return xh.getX() * xh.getY() - xh.getX() / 2 - xh.getY() / 2 + 1.0 / 4.0;
			}
			else if (basis_der_x == 2 && basis_der_y == 0)
			{
				return xh.getY() * (xh.getY() - 1) / 2;
			}
			else if (basis_der_x == 0 && basis_der_y == 2)
			{
				return xh.getX() * (xh.getX() - 1) / 2;
			}
			else if (basis_der_x == 3 && basis_der_y == 0)
			{
				return 0;
			}
			else if (basis_der_x == 0 && basis_der_y == 3)
			{
				return 0;
			}
			else if (basis_der_x == 2 && basis_der_y == 1)
			{
				return xh.getY() - 1 / 2;
			}
			else if (basis_der_x == 1 && basis_der_y == 2)
			{
				return xh.getX() - 1 / 2;
			}
			else if (basis_der_x == 2 && basis_der_y == 2)
			{
				return 1;
			}
			else
				return 0;
		}
		else if (basis_index == 1)
		{
			if (basis_der_x == 0 && basis_der_y == 0)
			{
				return -pow(xh.getX(), 2) * pow(xh.getY(), 2) / 2 + pow(xh.getX(), 2) * xh.getY() / 2 + pow(xh.getY(), 2) / 2 - xh.getY() / 2;
			}
			else if (basis_der_x == 1 && basis_der_y == 0)
			{
				return -xh.getX() * pow(xh.getY(), 2) + xh.getX() * xh.getY();
			}
			else if (basis_der_x == 0 && basis_der_y == 1)
			{
				return -pow(xh.getX(), 2) * xh.getY() + pow(xh.getX(), 2) / 2 + xh.getY() - 1.0 / 2.0;
			}
			else if (basis_der_x == 1 && basis_der_y == 1)
			{
				return xh.getX() * (1 - 2 * xh.getY());
			}
			else if (basis_der_x == 2 && basis_der_y == 0)
			{
				return xh.getY() * (1 - xh.getY());
			}
			else if (basis_der_x == 0 && basis_der_y == 2)
			{
				return 1 - pow(xh.getX(), 2);
			}
			else if (basis_der_x == 3 && basis_der_y == 0)
			{
				return 0;
			}
			else if (basis_der_x == 0 && basis_der_y == 3)
			{
				return 0;
			}
			else if (basis_der_x == 2 && basis_der_y == 1)
			{
				return 1 - 2 * xh.getY();
			}
			else if (basis_der_x == 1 && basis_der_y == 2)
			{
				return -2 * xh.getY();
			}
			else if (basis_der_x == 2 && basis_der_y == 2)
			{
				return -2.0;
			}
			else
				return 0;
		}
		else if (basis_index == 2)
		{
			if (basis_der_x == 0 && basis_der_y == 0)
			{
				return pow(xh.getX(), 2) * pow(xh.getY(), 2) / 4 - pow(xh.getX(), 2) * xh.getY() / 4 + xh.getX() * pow(xh.getY(), 2) / 4 - xh.getX() * xh.getY() / 4;
			}
			else if (basis_der_x == 1 && basis_der_y == 0)
			{
				return xh.getX() * pow(xh.getY(), 2) / 2 - xh.getX() * xh.getY() / 2 + pow(xh.getY(), 2) / 4 - xh.getY() / 4;
			}
			else if (basis_der_x == 0 && basis_der_y == 1)
			{
				return pow(xh.getX(), 2) * xh.getY() / 2 - pow(xh.getX(), 2) / 4 + xh.getX() * xh.getY() / 2 - xh.getX() / 4;
			}
			else if (basis_der_x == 1 && basis_der_y == 1)
			{
				return xh.getX() * xh.getY() - xh.getX() / 2 + xh.getY() / 2 - 1.0 / 4.0;
			}
			else if (basis_der_x == 2 && basis_der_y == 0)
			{
				return xh.getY() * (xh.getY() - 1) / 2;
			}
			else if (basis_der_x == 0 && basis_der_y == 2)
			{
				return xh.getX() * (xh.getX() + 1) / 2;
			}
			else if (basis_der_x == 3 && basis_der_y == 0)
			{
				return 0;
			}
			else if (basis_der_x == 0 && basis_der_y == 3)
			{
				return 0;
			}
			else if (basis_der_x == 2 && basis_der_y == 1)
			{
				return xh.getY() - 1.0 / 2.0;
			}
			else if (basis_der_x == 1 && basis_der_y == 2)
			{
				return xh.getX() + 1.0 / 2.0;
			}
			else if (basis_der_x == 2 && basis_der_y == 2)
			{
				return 1;
			}
			else
				return 0;
		}
		else if (basis_index == 3)
		{
			if (basis_der_x == 0 && basis_der_y == 0)
			{
				return -pow(xh.getX(), 2) * pow(xh.getY(), 2) / 2 + pow(xh.getX(), 2) / 2 - xh.getX() * pow(xh.getY(), 2) / 2 + xh.getX() / 2;
			}
			else if (basis_der_x == 1 && basis_der_y == 0)
			{
				return -xh.getX() * pow(xh.getY(), 2) + xh.getX() - pow(xh.getY(), 2) / 2 + 1.0 / 2.0;
			}
			else if (basis_der_x == 0 && basis_der_y == 1)
			{
				return -pow(xh.getX(), 2)* xh.getY() - xh.getX() * xh.getY();
			}
			else if (basis_der_x == 1 && basis_der_y == 1)
			{
				return -xh.getY() * (2 * xh.getX() + 1);
			}
			else if (basis_der_x == 2 && basis_der_y == 0)
			{
				return 1 - pow(xh.getY(), 2);
			}
			else if (basis_der_x == 0 && basis_der_y == 2)
			{
				return -xh.getX() * (xh.getX() + 1);
			}
			else if (basis_der_x == 3 && basis_der_y == 0)
			{
				return 0;
			}
			else if (basis_der_x == 0 && basis_der_y == 3)
			{
				return 0;
			}
			else if (basis_der_x == 2 && basis_der_y == 1)
			{
				return -2 * xh.getY();
			}
			else if (basis_der_x == 1 && basis_der_y == 2)
			{
				return -(2 * xh.getX() + 1.0);
			}
			else if (basis_der_x == 2 && basis_der_y == 2)
			{
				return -2;
			}
			else
				return 0;
		}
		else if (basis_index == 4)
		{
			if (basis_der_x == 0 && basis_der_y == 0)
			{
				return pow(x, 2) * pow(y, 2) / 4 + pow(x, 2) * y / 4 + x * pow(y, 2) / 4 + x * y / 4;
			}
			else if (basis_der_x == 1 && basis_der_y == 0)
			{
				return x * pow(y, 2) / 2 + x * y / 2 + pow(y, 2) / 4 + y / 4;
			}
			else if (basis_der_x == 0 && basis_der_y == 1)
			{
				return pow(x, 2) * y / 2 + pow(x, 2) / 4 + x * y / 2 + x / 4;
			}
			else if (basis_der_x == 1 && basis_der_y == 1)
			{
				return x * y + x / 2 + y / 2 + 1.0 / 4.0;
			}
			else if (basis_der_x == 2 && basis_der_y == 0)
			{
				return y * (y + 1) / 2;
			}
			else if (basis_der_x == 0 && basis_der_y == 2)
			{
				return x * (x + 1) / 2;
			}
			else if (basis_der_x == 3 && basis_der_y == 0)
			{
				return 0;
			}
			else if (basis_der_x == 0 && basis_der_y == 3)
			{
				return 0;
			}
			else if (basis_der_x == 2 && basis_der_y == 1)
			{
				return y + 1 / 2.0;
			}
			else if (basis_der_x == 1 && basis_der_y == 2)
			{
				return x + 1 / 2.0;
			}
			else if (basis_der_x == 2 && basis_der_y == 2)
			{
				return 1;
			}
			else
				return 0;
		}

		else if (basis_index == 5)
		{
			if (basis_der_x == 0 && basis_der_y == 0)
			{
				return -pow(x, 2)* pow(y, 2) / 2 - pow(x, 2) * y / 2 + pow(y, 2) / 2 + y / 2;
			}
			else if (basis_der_x == 1 && basis_der_y == 0)
			{
				return -x * pow(y, 2) - x * y;
			}
			else if (basis_der_x == 0 && basis_der_y == 1)
			{
				return -pow(x, 2) * y - pow(x, 2) / 2 + y + 1.0 / 2.0;
			}
			else if (basis_der_x == 1 && basis_der_y == 1)
			{
				return -x * (2 * y + 1);
			}
			else if (basis_der_x == 2 && basis_der_y == 0)
			{
				return -y * (y + 1);
			}
			else if (basis_der_x == 0 && basis_der_y == 2)
			{
				return 1 - pow(x, 2);
			}
			else if (basis_der_x == 3 && basis_der_y == 0)
			{
				return 0;
			}
			else if (basis_der_x == 0 && basis_der_y == 3)
			{
				return 0;
			}
			else if (basis_der_x == 2 && basis_der_y == 1)
			{
				return -(2 * y + 1);
			}
			else if (basis_der_x == 1 && basis_der_y == 2)
			{
				return -2 * x;
			}
			else if (basis_der_x == 2 && basis_der_y == 2)
			{
				return -2;
			}
			else
				return 0;
		}
		else if (basis_index == 6)
		{
			if (basis_der_x == 0 && basis_der_y == 0)
			{
				return pow(x, 2) * pow(y, 2) / 4 + pow(x, 2) * y / 4 - x * pow(y, 2) / 4 - x * y / 4;
			}
			else if (basis_der_x == 1 && basis_der_y == 0)
			{
				return x * pow(y, 2) / 2 + x * y / 2 - pow(y, 2) / 4 - y / 4;
			}
			else if (basis_der_x == 0 && basis_der_y == 1)
			{
				return pow(x, 2) * y / 2 + pow(x, 2) / 4 - x * y / 2 - x / 4;
			}
			else if (basis_der_x == 1 && basis_der_y == 1)
			{
				return x * y + x / 2 - y / 2 - 1 / 4;
			}
			else if (basis_der_x == 2 && basis_der_y == 0)
			{
				return y * (y + 1) / 2;
			}
			else if (basis_der_x == 0 && basis_der_y == 2)
			{
				return x * (x - 1) / 2;
			}
			else if (basis_der_x == 3 && basis_der_y == 0)
			{
				return 0;
			}
			else if (basis_der_x == 0 && basis_der_y == 3)
			{
				return 0;
			}
			else if (basis_der_x == 2 && basis_der_y == 1)
			{
				return y + 1.0 / 2.0;
			}
			else if (basis_der_x == 1 && basis_der_y == 2)
			{
				return x - 1.0 / 2.0;
			}
			else if (basis_der_x == 2 && basis_der_y == 2)
			{
				return 1;
			}
			else
				return 0;
		}
		else if (basis_index == 7)
		{
			if (basis_der_x == 0 && basis_der_y == 0)
			{
				return -pow(x, 2) * pow(y, 2) / 2 + pow(x, 2) / 2 + x * pow(y, 2) / 2 - x / 2;
			}
			else if (basis_der_x == 1 && basis_der_y == 0)
			{
				return -x * pow(y, 2) + x + pow(y, 2) / 2 - 1.0 / 2.0;
			}
			else if (basis_der_x == 0 && basis_der_y == 1)
			{
				return -pow(x, 2) * y + x * y;
			}
			else if (basis_der_x == 1 && basis_der_y == 1)
			{
				return y * (1 - 2 * x);
			}
			else if (basis_der_x == 2 && basis_der_y == 0)
			{
				return 1 - pow(y, 2);
			}
			else if (basis_der_x == 0 && basis_der_y == 2)
			{
				return x * (1 - x);
			}
			else if (basis_der_x == 3 && basis_der_y == 0)
			{
				return 0;
			}
			else if (basis_der_x == 0 && basis_der_y == 3)
			{
				return 0;
			}
			else if (basis_der_x == 2 && basis_der_y == 1)
			{
				return -2 * y;
			}
			else if (basis_der_x == 1 && basis_der_y == 2)
			{
				return 1 - 2 * x;
			}
			else if (basis_der_x == 2 && basis_der_y == 2)
			{
				return -2;
			}
			else
				return 0;
		}
		else if (basis_index == 8)
		{
			if (basis_der_x == 0 && basis_der_y == 0)
			{
				return pow(x, 2) * pow(y, 2) - pow(x, 2) - pow(y, 2) + 1;
			}
			else if (basis_der_x == 1 && basis_der_y == 0)
			{
				return 2 * x*pow(y, 2) - 2 * x;
			}
			else if (basis_der_x == 0 && basis_der_y == 1)
			{
				return 2 * pow(x, 2) * y - 2 * y;
			}
			else if (basis_der_x == 1 && basis_der_y == 1)
			{
				return 4 * x*y;
			}
			else if (basis_der_x == 2 && basis_der_y == 0)
			{
				return 2 * (pow(y, 2) - 1);
			}
			else if (basis_der_x == 0 && basis_der_y == 2)
			{
				return 2 * (pow(x, 2) - 1);
			}
			else if (basis_der_x == 3 && basis_der_y == 0)
			{
				return 0;
			}
			else if (basis_der_x == 0 && basis_der_y == 3)
			{
				return 0;
			}
			else if (basis_der_x == 2 && basis_der_y == 1)
			{
				return 4 * y;
			}
			else if (basis_der_x == 1 && basis_der_y == 2)
			{
				return 4 * x;
			}
			else if (basis_der_x == 2 && basis_der_y == 2)
			{
				return 4;
			}
			else
				return 0;
		}

	}
	return 0;
}
